package com.cencat.route.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cencat.common.result.Result;
import com.cencat.route.entity.Merchant;
import com.cencat.route.service.MerchantService;
import com.cencat.route.vo.MerchantQueryVO;
import com.cencat.route.vo.MerchantStatisticsVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * 商户管理控制器
 * 
 * @author cencat
 * @since 2024-01-01
 */
@Slf4j
@RestController
@RequestMapping("/api/route/merchant")
@RequiredArgsConstructor
@Tag(name = "商户管理", description = "商户信息的增删改查和业务操作")
public class MerchantController {

    private final MerchantService merchantService;

    @GetMapping("/page")
    @Operation(summary = "分页查询商户", description = "根据条件分页查询商户信息")
    public Result<Page<Merchant>> getMerchantPage(
            @Parameter(description = "页码", example = "1") @RequestParam(defaultValue = "1") Long current,
            @Parameter(description = "每页大小", example = "10") @RequestParam(defaultValue = "10") Long size,
            @Parameter(description = "查询条件") MerchantQueryVO query) {
        try {
            Page<Merchant> page = new Page<>(current, size);
            Page<Merchant> result = merchantService.selectMerchantPage(page, query);
            return Result.success(result);
        } catch (Exception e) {
            log.error("分页查询商户失败: {}", e.getMessage(), e);
            return Result.error("分页查询商户失败: " + e.getMessage());
        }
    }

    @GetMapping("/list")
    @Operation(summary = "查询商户列表", description = "根据条件查询商户列表")
    public Result<List<Merchant>> getMerchantList(@Parameter(description = "查询条件") MerchantQueryVO query) {
        try {
            List<Merchant> result = merchantService.selectMerchantList(query);
            return Result.success(result);
        } catch (Exception e) {
            log.error("查询商户列表失败: {}", e.getMessage(), e);
            return Result.error("查询商户列表失败: " + e.getMessage());
        }
    }

    @GetMapping("/{id}")
    @Operation(summary = "根据ID查询商户", description = "根据商户ID查询详细信息")
    public Result<Merchant> getMerchantById(@Parameter(description = "商户ID") @PathVariable Long id) {
        try {
            Merchant merchant = merchantService.getById(id);
            if (merchant == null) {
                return Result.error("商户不存在");
            }
            return Result.success(merchant);
        } catch (Exception e) {
            log.error("查询商户详情失败: {}", e.getMessage(), e);
            return Result.error("查询商户详情失败: " + e.getMessage());
        }
    }

    @PostMapping
    @Operation(summary = "新增商户", description = "创建新的商户信息")
    public Result<Boolean> createMerchant(@Parameter(description = "商户信息") @Valid @RequestBody Merchant merchant) {
        try {
            boolean result = merchantService.save(merchant);
            return result ? Result.success(true) : Result.error("新增商户失败");
        } catch (Exception e) {
            log.error("新增商户失败: {}", e.getMessage(), e);
            return Result.error("新增商户失败: " + e.getMessage());
        }
    }

    @PutMapping
    @Operation(summary = "更新商户", description = "更新商户信息")
    public Result<Boolean> updateMerchant(@Parameter(description = "商户信息") @Valid @RequestBody Merchant merchant) {
        try {
            boolean result = merchantService.updateById(merchant);
            return result ? Result.success(true) : Result.error("更新商户失败");
        } catch (Exception e) {
            log.error("更新商户失败: {}", e.getMessage(), e);
            return Result.error("更新商户失败: " + e.getMessage());
        }
    }

    @DeleteMapping("/{id}")
    @Operation(summary = "删除商户", description = "根据ID删除商户")
    public Result<Boolean> deleteMerchant(@Parameter(description = "商户ID") @PathVariable Long id) {
        try {
            boolean result = merchantService.removeById(id);
            return result ? Result.success(true) : Result.error("删除商户失败");
        } catch (Exception e) {
            log.error("删除商户失败: {}", e.getMessage(), e);
            return Result.error("删除商户失败: " + e.getMessage());
        }
    }

    @PutMapping("/batch/status")
    @Operation(summary = "批量更新商户状态", description = "批量更新商户状态")
    public Result<Boolean> batchUpdateMerchantStatus(
            @Parameter(description = "商户ID列表") @RequestBody List<Long> ids,
            @Parameter(description = "状态") @RequestParam String status,
            @Parameter(description = "更新人ID") @RequestParam Long updatedBy) {
        try {
            boolean result = merchantService.batchUpdateMerchantStatus(ids, status, updatedBy);
            return result ? Result.success(true) : Result.error("批量更新商户状态失败");
        } catch (Exception e) {
            log.error("批量更新商户状态失败: {}", e.getMessage(), e);
            return Result.error("批量更新商户状态失败: " + e.getMessage());
        }
    }

    @PutMapping("/batch/verification-status")
    @Operation(summary = "批量更新认证状态", description = "批量更新商户认证状态")
    public Result<Boolean> batchUpdateVerificationStatus(
            @Parameter(description = "商户ID列表") @RequestBody List<Long> ids,
            @Parameter(description = "认证状态") @RequestParam String verificationStatus,
            @Parameter(description = "更新人ID") @RequestParam Long updatedBy) {
        try {
            boolean result = merchantService.batchUpdateVerificationStatus(ids, verificationStatus, updatedBy);
            return result ? Result.success(true) : Result.error("批量更新认证状态失败");
        } catch (Exception e) {
            log.error("批量更新认证状态失败: {}", e.getMessage(), e);
            return Result.error("批量更新认证状态失败: " + e.getMessage());
        }
    }

    @PutMapping("/batch/credit-score")
    @Operation(summary = "批量更新信用分数", description = "批量更新商户信用分数")
    public Result<Boolean> batchUpdateCreditScore(
            @Parameter(description = "商户ID列表") @RequestBody List<Long> ids,
            @Parameter(description = "信用分数") @RequestParam Integer creditScore,
            @Parameter(description = "更新人ID") @RequestParam Long updatedBy) {
        try {
            boolean result = merchantService.batchUpdateCreditScore(ids, creditScore, updatedBy);
            return result ? Result.success(true) : Result.error("批量更新信用分数失败");
        } catch (Exception e) {
            log.error("批量更新信用分数失败: {}", e.getMessage(), e);
            return Result.error("批量更新信用分数失败: " + e.getMessage());
        }
    }

    @PutMapping("/batch/credit-level")
    @Operation(summary = "批量更新信用等级", description = "批量更新商户信用等级")
    public Result<Boolean> batchUpdateCreditLevel(
            @Parameter(description = "商户ID列表") @RequestBody List<Long> ids,
            @Parameter(description = "信用等级") @RequestParam String creditLevel,
            @Parameter(description = "更新人ID") @RequestParam Long updatedBy) {
        try {
            boolean result = merchantService.batchUpdateCreditLevel(ids, creditLevel, updatedBy);
            return result ? Result.success(true) : Result.error("批量更新信用等级失败");
        } catch (Exception e) {
            log.error("批量更新信用等级失败: {}", e.getMessage(), e);
            return Result.error("批量更新信用等级失败: " + e.getMessage());
        }
    }

    @GetMapping("/statistics")
    @Operation(summary = "获取商户统计信息", description = "获取商户相关统计数据")
    public Result<MerchantStatisticsVO> getMerchantStatistics() {
        try {
            MerchantStatisticsVO result = merchantService.getMerchantStatistics();
            return Result.success(result);
        } catch (Exception e) {
            log.error("获取商户统计信息失败: {}", e.getMessage(), e);
            return Result.error("获取商户统计信息失败: " + e.getMessage());
        }
    }

    @PostMapping("/credit-assessment/{id}")
    @Operation(summary = "信用评估", description = "对商户进行信用评估")
    public Result<String> performCreditAssessment(
            @Parameter(description = "商户ID") @PathVariable Long id,
            @Parameter(description = "评估参数") @RequestParam String assessmentParams,
            @Parameter(description = "评估人ID") @RequestParam Long assessedBy) {
        try {
            String result = merchantService.performCreditAssessment(id, assessmentParams, assessedBy);
            return Result.success(result);
        } catch (Exception e) {
            log.error("信用评估失败: {}", e.getMessage(), e);
            return Result.error("信用评估失败: " + e.getMessage());
        }
    }

    @GetMapping("/business-analysis/{id}")
    @Operation(summary = "业务分析", description = "分析商户业务数据")
    public Result<String> performBusinessAnalysis(
            @Parameter(description = "商户ID") @PathVariable Long id,
            @Parameter(description = "分析类型") @RequestParam String analysisType) {
        try {
            String result = merchantService.performBusinessAnalysis(id, analysisType);
            return Result.success(result);
        } catch (Exception e) {
            log.error("业务分析失败: {}", e.getMessage(), e);
            return Result.error("业务分析失败: " + e.getMessage());
        }
    }

    @GetMapping("/active")
    @Operation(summary = "获取活跃商户列表", description = "获取活跃状态的商户列表")
    public Result<List<Merchant>> getActiveMerchants(
            @Parameter(description = "限制数量") @RequestParam(defaultValue = "50") Integer limit) {
        try {
            List<Merchant> result = merchantService.getActiveMerchants(limit);
            return Result.success(result);
        } catch (Exception e) {
            log.error("获取活跃商户列表失败: {}", e.getMessage(), e);
            return Result.error("获取活跃商户列表失败: " + e.getMessage());
        }
    }

    @GetMapping("/verified")
    @Operation(summary = "获取已认证商户列表", description = "获取已通过认证的商户列表")
    public Result<List<Merchant>> getVerifiedMerchants(
            @Parameter(description = "限制数量") @RequestParam(defaultValue = "50") Integer limit) {
        try {
            List<Merchant> result = merchantService.getVerifiedMerchants(limit);
            return Result.success(result);
        } catch (Exception e) {
            log.error("获取已认证商户列表失败: {}", e.getMessage(), e);
            return Result.error("获取已认证商户列表失败: " + e.getMessage());
        }
    }

    @GetMapping("/pending-verification")
    @Operation(summary = "获取待认证商户列表", description = "获取待认证的商户列表")
    public Result<List<Merchant>> getPendingVerificationMerchants(
            @Parameter(description = "限制数量") @RequestParam(defaultValue = "30") Integer limit) {
        try {
            List<Merchant> result = merchantService.getPendingVerificationMerchants(limit);
            return Result.success(result);
        } catch (Exception e) {
            log.error("获取待认证商户列表失败: {}", e.getMessage(), e);
            return Result.error("获取待认证商户列表失败: " + e.getMessage());
        }
    }

    @GetMapping("/high-credit")
    @Operation(summary = "获取高信用商户列表", description = "获取高信用等级的商户列表")
    public Result<List<Merchant>> getHighCreditMerchants(
            @Parameter(description = "最低信用分数") @RequestParam(defaultValue = "80") Integer minCreditScore,
            @Parameter(description = "限制数量") @RequestParam(defaultValue = "30") Integer limit) {
        try {
            List<Merchant> result = merchantService.getHighCreditMerchants(minCreditScore, limit);
            return Result.success(result);
        } catch (Exception e) {
            log.error("获取高信用商户列表失败: {}", e.getMessage(), e);
            return Result.error("获取高信用商户列表失败: " + e.getMessage());
        }
    }

    @GetMapping("/low-credit")
    @Operation(summary = "获取低信用商户列表", description = "获取低信用等级的商户列表")
    public Result<List<Merchant>> getLowCreditMerchants(
            @Parameter(description = "最高信用分数") @RequestParam(defaultValue = "40") Integer maxCreditScore,
            @Parameter(description = "限制数量") @RequestParam(defaultValue = "30") Integer limit) {
        try {
            List<Merchant> result = merchantService.getLowCreditMerchants(maxCreditScore, limit);
            return Result.success(result);
        } catch (Exception e) {
            log.error("获取低信用商户列表失败: {}", e.getMessage(), e);
            return Result.error("获取低信用商户列表失败: " + e.getMessage());
        }
    }

    @GetMapping("/new-registered")
    @Operation(summary = "获取新注册商户列表", description = "获取最近注册的商户列表")
    public Result<List<Merchant>> getNewRegisteredMerchants(
            @Parameter(description = "天数") @RequestParam(defaultValue = "7") Integer days,
            @Parameter(description = "限制数量") @RequestParam(defaultValue = "30") Integer limit) {
        try {
            List<Merchant> result = merchantService.getNewRegisteredMerchants(days, limit);
            return Result.success(result);
        } catch (Exception e) {
            log.error("获取新注册商户列表失败: {}", e.getMessage(), e);
            return Result.error("获取新注册商户列表失败: " + e.getMessage());
        }
    }

    @GetMapping("/by-type/{merchantType}")
    @Operation(summary = "根据类型获取商户列表", description = "获取指定类型的商户列表")
    public Result<List<Merchant>> getMerchantsByType(
            @Parameter(description = "商户类型") @PathVariable String merchantType,
            @Parameter(description = "限制数量") @RequestParam(defaultValue = "50") Integer limit) {
        try {
            List<Merchant> result = merchantService.getMerchantsByType(merchantType, limit);
            return Result.success(result);
        } catch (Exception e) {
            log.error("根据类型获取商户列表失败: {}", e.getMessage(), e);
            return Result.error("根据类型获取商户列表失败: " + e.getMessage());
        }
    }

    @GetMapping("/by-region/{region}")
    @Operation(summary = "根据地区获取商户列表", description = "获取指定地区的商户列表")
    public Result<List<Merchant>> getMerchantsByRegion(
            @Parameter(description = "地区") @PathVariable String region,
            @Parameter(description = "限制数量") @RequestParam(defaultValue = "50") Integer limit) {
        try {
            List<Merchant> result = merchantService.getMerchantsByRegion(region, limit);
            return Result.success(result);
        } catch (Exception e) {
            log.error("根据地区获取商户列表失败: {}", e.getMessage(), e);
            return Result.error("根据地区获取商户列表失败: " + e.getMessage());
        }
    }

    @GetMapping("/check/exists/{id}")
    @Operation(summary = "检查商户是否存在", description = "根据ID检查商户是否存在")
    public Result<Boolean> checkMerchantExists(@Parameter(description = "商户ID") @PathVariable Long id) {
        try {
            boolean result = merchantService.checkMerchantExists(id);
            return Result.success(result);
        } catch (Exception e) {
            log.error("检查商户是否存在失败: {}", e.getMessage(), e);
            return Result.error("检查商户是否存在失败: " + e.getMessage());
        }
    }

    @GetMapping("/check/code")
    @Operation(summary = "检查商户编码是否存在", description = "检查商户编码是否已被使用")
    public Result<Boolean> checkMerchantCodeExists(
            @Parameter(description = "商户编码") @RequestParam String merchantCode,
            @Parameter(description = "排除的商户ID") @RequestParam(required = false) Long excludeId) {
        try {
            boolean result = merchantService.checkMerchantCodeExists(merchantCode, excludeId);
            return Result.success(result);
        } catch (Exception e) {
            log.error("检查商户编码是否存在失败: {}", e.getMessage(), e);
            return Result.error("检查商户编码是否存在失败: " + e.getMessage());
        }
    }

    @PostMapping("/register")
    @Operation(summary = "注册商户", description = "注册新的商户")
    public Result<Boolean> registerMerchant(
            @Parameter(description = "商户信息") @Valid @RequestBody Merchant merchant,
            @Parameter(description = "注册人ID") @RequestParam Long registeredBy) {
        try {
            boolean result = merchantService.registerMerchant(merchant, registeredBy);
            return result ? Result.success(true) : Result.error("注册商户失败");
        } catch (Exception e) {
            log.error("注册商户失败: {}", e.getMessage(), e);
            return Result.error("注册商户失败: " + e.getMessage());
        }
    }

    @PutMapping("/verify/{id}")
    @Operation(summary = "认证商户", description = "对商户进行认证")
    public Result<Boolean> verifyMerchant(
            @Parameter(description = "商户ID") @PathVariable Long id,
            @Parameter(description = "认证结果") @RequestParam Boolean verificationResult,
            @Parameter(description = "认证备注") @RequestParam(required = false) String verificationNotes,
            @Parameter(description = "认证人ID") @RequestParam Long verifiedBy) {
        try {
            boolean result = merchantService.verifyMerchant(id, verificationResult, verificationNotes, verifiedBy);
            return result ? Result.success(true) : Result.error("认证商户失败");
        } catch (Exception e) {
            log.error("认证商户失败: {}", e.getMessage(), e);
            return Result.error("认证商户失败: " + e.getMessage());
        }
    }

    @PutMapping("/activate/{id}")
    @Operation(summary = "激活商户", description = "激活商户账户")
    public Result<Boolean> activateMerchant(
            @Parameter(description = "商户ID") @PathVariable Long id,
            @Parameter(description = "激活人ID") @RequestParam Long activatedBy) {
        try {
            boolean result = merchantService.activateMerchant(id, activatedBy);
            return result ? Result.success(true) : Result.error("激活商户失败");
        } catch (Exception e) {
            log.error("激活商户失败: {}", e.getMessage(), e);
            return Result.error("激活商户失败: " + e.getMessage());
        }
    }

    @PutMapping("/deactivate/{id}")
    @Operation(summary = "停用商户", description = "停用商户账户")
    public Result<Boolean> deactivateMerchant(
            @Parameter(description = "商户ID") @PathVariable Long id,
            @Parameter(description = "停用原因") @RequestParam String deactivationReason,
            @Parameter(description = "停用人ID") @RequestParam Long deactivatedBy) {
        try {
            boolean result = merchantService.deactivateMerchant(id, deactivationReason, deactivatedBy);
            return result ? Result.success(true) : Result.error("停用商户失败");
        } catch (Exception e) {
            log.error("停用商户失败: {}", e.getMessage(), e);
            return Result.error("停用商户失败: " + e.getMessage());
        }
    }

    @PutMapping("/suspend/{id}")
    @Operation(summary = "暂停商户", description = "暂停商户服务")
    public Result<Boolean> suspendMerchant(
            @Parameter(description = "商户ID") @PathVariable Long id,
            @Parameter(description = "暂停原因") @RequestParam String suspensionReason,
            @Parameter(description = "暂停人ID") @RequestParam Long suspendedBy) {
        try {
            boolean result = merchantService.suspendMerchant(id, suspensionReason, suspendedBy);
            return result ? Result.success(true) : Result.error("暂停商户失败");
        } catch (Exception e) {
            log.error("暂停商户失败: {}", e.getMessage(), e);
            return Result.error("暂停商户失败: " + e.getMessage());
        }
    }

    @PutMapping("/resume/{id}")
    @Operation(summary = "恢复商户", description = "恢复商户服务")
    public Result<Boolean> resumeMerchant(
            @Parameter(description = "商户ID") @PathVariable Long id,
            @Parameter(description = "恢复人ID") @RequestParam Long resumedBy) {
        try {
            boolean result = merchantService.resumeMerchant(id, resumedBy);
            return result ? Result.success(true) : Result.error("恢复商户失败");
        } catch (Exception e) {
            log.error("恢复商户失败: {}", e.getMessage(), e);
            return Result.error("恢复商户失败: " + e.getMessage());
        }
    }

    @PutMapping("/update-credit-score/{id}")
    @Operation(summary = "更新信用分数", description = "更新商户信用分数")
    public Result<Boolean> updateCreditScore(
            @Parameter(description = "商户ID") @PathVariable Long id,
            @Parameter(description = "信用分数") @RequestParam Integer creditScore,
            @Parameter(description = "更新原因") @RequestParam(required = false) String updateReason,
            @Parameter(description = "更新人ID") @RequestParam Long updatedBy) {
        try {
            boolean result = merchantService.updateCreditScore(id, creditScore, updateReason, updatedBy);
            return result ? Result.success(true) : Result.error("更新信用分数失败");
        } catch (Exception e) {
            log.error("更新信用分数失败: {}", e.getMessage(), e);
            return Result.error("更新信用分数失败: " + e.getMessage());
        }
    }

    @PutMapping("/update-credit-level/{id}")
    @Operation(summary = "更新信用等级", description = "更新商户信用等级")
    public Result<Boolean> updateCreditLevel(
            @Parameter(description = "商户ID") @PathVariable Long id,
            @Parameter(description = "信用等级") @RequestParam String creditLevel,
            @Parameter(description = "更新原因") @RequestParam(required = false) String updateReason,
            @Parameter(description = "更新人ID") @RequestParam Long updatedBy) {
        try {
            boolean result = merchantService.updateCreditLevel(id, creditLevel, updateReason, updatedBy);
            return result ? Result.success(true) : Result.error("更新信用等级失败");
        } catch (Exception e) {
            log.error("更新信用等级失败: {}", e.getMessage(), e);
            return Result.error("更新信用等级失败: " + e.getMessage());
        }
    }

    @PutMapping("/update-contact/{id}")
    @Operation(summary = "更新联系信息", description = "更新商户联系信息")
    public Result<Boolean> updateContactInfo(
            @Parameter(description = "商户ID") @PathVariable Long id,
            @Parameter(description = "联系人") @RequestParam String contactPerson,
            @Parameter(description = "联系电话") @RequestParam String contactPhone,
            @Parameter(description = "联系邮箱") @RequestParam(required = false) String contactEmail,
            @Parameter(description = "更新人ID") @RequestParam Long updatedBy) {
        try {
            boolean result = merchantService.updateContactInfo(id, contactPerson, contactPhone, contactEmail, updatedBy);
            return result ? Result.success(true) : Result.error("更新联系信息失败");
        } catch (Exception e) {
            log.error("更新联系信息失败: {}", e.getMessage(), e);
            return Result.error("更新联系信息失败: " + e.getMessage());
        }
    }

    @PutMapping("/update-address/{id}")
    @Operation(summary = "更新地址信息", description = "更新商户地址信息")
    public Result<Boolean> updateAddressInfo(
            @Parameter(description = "商户ID") @PathVariable Long id,
            @Parameter(description = "详细地址") @RequestParam String address,
            @Parameter(description = "省份") @RequestParam(required = false) String province,
            @Parameter(description = "城市") @RequestParam(required = false) String city,
            @Parameter(description = "区县") @RequestParam(required = false) String district,
            @Parameter(description = "更新人ID") @RequestParam Long updatedBy) {
        try {
            boolean result = merchantService.updateAddressInfo(id, address, province, city, district, updatedBy);
            return result ? Result.success(true) : Result.error("更新地址信息失败");
        } catch (Exception e) {
            log.error("更新地址信息失败: {}", e.getMessage(), e);
            return Result.error("更新地址信息失败: " + e.getMessage());
        }
    }

    @PostMapping("/calculate-credit-score/{id}")
    @Operation(summary = "计算信用分数", description = "根据商户数据计算信用分数")
    public Result<Integer> calculateCreditScore(
            @Parameter(description = "商户ID") @PathVariable Long id,
            @Parameter(description = "计算参数") @RequestParam(required = false) String calculationParams) {
        try {
            Integer result = merchantService.calculateCreditScore(id, calculationParams);
            return Result.success(result);
        } catch (Exception e) {
            log.error("计算信用分数失败: {}", e.getMessage(), e);
            return Result.error("计算信用分数失败: " + e.getMessage());
        }
    }

    @PostMapping("/generate-report/{id}")
    @Operation(summary = "生成商户报告", description = "生成商户业务报告")
    public Result<String> generateMerchantReport(
            @Parameter(description = "商户ID") @PathVariable Long id,
            @Parameter(description = "报告类型") @RequestParam String reportType,
            @Parameter(description = "报告参数") @RequestParam(required = false) String reportParams) {
        try {
            String result = merchantService.generateMerchantReport(id, reportType, reportParams);
            return Result.success(result);
        } catch (Exception e) {
            log.error("生成商户报告失败: {}", e.getMessage(), e);
            return Result.error("生成商户报告失败: " + e.getMessage());
        }
    }

}